﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using JEdwonTune.Lib.Jskit;
using System.Text.RegularExpressions;
using System.Xml;
using JEdwonTune.Lib;

namespace JEdwonTune.Jskit {
    public partial class FrmBuildJsPackage : FrmMDIChild {
        public FrmBuildJsPackage() {
            InitializeComponent();
        }
        private String _JskitPath;
        public String JskitPath {
            set { _JskitPath = value; }
            get { return _JskitPath; }
        }
        XmlDocument doc = new XmlDocument();
        private Boolean loaded = false;

        private void FrmJskitView_Load(object sender, EventArgs e) {

        }


        #region 打开文件夹的方式
        private void saveLastFolder(String folder) {
            String filepath = System.Environment.CurrentDirectory + @"\" + MyUtil.OPTION_FILENAME;
            XmlDocument doc = new XmlDocument();
            if (File.Exists(filepath)) {
                doc.Load(filepath);
            } else {
                doc.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?><jskit></jskit>");
            }
            XmlNode node = doc.SelectSingleNode("//build-jspackage-folder");
            if (node == null) {
                node = doc.CreateElement("build-jspackage-folder");
                XmlAttribute attr = doc.CreateAttribute("value");
                attr.Value = folder;
                node.Attributes.Append(attr);
                doc.DocumentElement.AppendChild(node);
            } else {
                node.Attributes["value"].Value = folder;
            }
            doc.Save(filepath);
        }
        private String loadLastFolder() {
            String filepath = System.Environment.CurrentDirectory + "\\" + MyUtil.OPTION_FILENAME;
            XmlDocument doc = new XmlDocument();
            if (File.Exists(filepath)) {
                doc.Load(filepath);
                XmlNode node = doc.SelectSingleNode("//build-jspackage-folder");
                if (node == null) return "";
                else
                    return node.Attributes["value"].Value;
            } else {
                return "";
            }
        }
        #endregion
        #region 打开Build.xml文件的方式
        private void saveLastFile(String path) {
            String filepath = System.Environment.CurrentDirectory + @"\" + MyUtil.OPTION_FILENAME;
            XmlDocument doc = new XmlDocument();
            if (File.Exists(filepath)) {
                doc.Load(filepath);
            } else {
                doc.LoadXml("<?xml version=\"1.0\" encoding=\"utf-8\"?><jskit></jskit>");
            }
            XmlNode node = doc.SelectSingleNode("//build-jspackage-path");
            if (node == null) {
                node = doc.CreateElement("build-jspackage-path");
                XmlAttribute attr = doc.CreateAttribute("value");
                attr.Value = path;
                node.Attributes.Append(attr);
                doc.DocumentElement.AppendChild(node);
            } else {
                node.Attributes["value"].Value = path;
            }
            doc.Save(filepath);
        }

        private String loadLastFile() {
            String filepath = System.Environment.CurrentDirectory + @"\" + MyUtil.OPTION_FILENAME;
            XmlDocument doc = new XmlDocument();
            if (File.Exists(filepath)) {
                doc.Load(filepath);
                XmlNode node = doc.SelectSingleNode("//build-jspackage-path");
                if (node == null) return "";
                else
                    return node.Attributes["value"].Value;
            } else {
                return "";
            }
        }
        #endregion
        #region Build xml 数据结构
        public class Package { 
            public String Name = "";
            public Boolean Build = true;
            public String OutPath = "";
            public IList<JsFile> FileList = new List<JsFile>();
        }
        public class Resource {
            public String Name = "";
            public Boolean Build = true;
            public IList<ResFile> FileList = new List<ResFile>();
        }
        public class ResFile {
            public String Name = "";
            public String Path = "";
            public String DstDir = "";
        }
        public class BuildDoc {
            public String Version = "";
            public String RootPath = "";
            public String OutPath = "";
            public IList<Package> PackageList = new List<Package>();
            public IList<Resource> ResourceList = new List<Resource>();
        }
        public class JsFile {
            public String Name = "";
            public String Path = "";
        }
        #endregion
        private BuildDoc parse2BuildDoc(XmlDocument doc) {
            XmlElement root = doc.DocumentElement;
            BuildDoc bd = new BuildDoc();
            bd.Version = readAttr(root, "ver", "");
            bd.RootPath = parseDir(readAttr(root, "path", "/"));
            bd.OutPath = parseDir(readAttr(root, "out", bd.RootPath));
            XmlNodeList pnl = root.SelectNodes("//package");
            foreach (XmlNode p in pnl) {
                Package pk = new Package();
                pk.Name = readAttr(p, "name", "unknown");
                pk.OutPath = bd.OutPath + pk.Name + ".js";
                pk.Build = (readAttr(p,"build","true")=="true");
                XmlNodeList fnl = p.SelectNodes("file");
                foreach (XmlNode f in fnl) {
                    JsFile jf = new JsFile();
                    jf.Name = readAttr(f, "name", "");
                    jf.Path = readAttr(f, "path", "");
                    if (!String.IsNullOrEmpty(jf.Name) 
                        && !String.IsNullOrEmpty(jf.Path)
                        && Regex.IsMatch(jf.Path,"\\.js$", RegexOptions.IgnoreCase)) {
                        jf.Path = (bd.RootPath + jf.Path).Replace("//", "/");
                    }
                    pk.FileList.Add(jf);
                }
                bd.PackageList.Add(pk);
            }

            XmlNodeList rnl = root.SelectNodes("//resource");
            foreach (XmlNode r in rnl) {
                Resource res = new Resource();
                res.Name = readAttr(r, "name", "unknown");
                res.Build = (readAttr(r, "build", "true") == "true");
                XmlNodeList fnl = r.SelectNodes("res");
                foreach (XmlNode f in fnl) {
                    ResFile rf = new ResFile();
                    rf.Name = readAttr(f, "name", "");
                    rf.Path = bd.RootPath+readAttr(f, "path", "");
                    rf.DstDir = bd.OutPath + parseDir(readAttr(f, "out", ""));
                    res.FileList.Add(rf);
                }
                bd.ResourceList.Add(res);
            }

            return bd;
        }

        public void ParseBuildConfig() {
            doc.Load(_JskitPath);
            loaded = true;
            BuildDoc bd = parse2BuildDoc(doc);
            this.listBox1.Items.Clear();
            this.listBox1.Items.Add(new MyListItem("------@ ROOT:[" + bd.RootPath + "]", ""));
            this.listBox1.Items.Add(new MyListItem("------@ OUT:[" + bd.OutPath + "]", ""));
            this.listBox1.Items.Add(new MyListItem("------@ VERSION:[" + bd.Version + "]", ""));
            foreach (Package p in bd.PackageList) {
                if (p.Build) {
                    this.listBox1.Items.Add(new MyListItem("------@ PACKAGE:[" + p.Name + "][Y] ------", ""));
                    foreach (JsFile f in p.FileList) {
                        this.listBox1.Items.Add(new MyListItem(f.Name, f.Path));
                    }
                } else {
                    this.listBox1.Items.Add(new MyListItem("------# PACKAGE:[" + p.Name + "][N] ------", ""));
                }

            }
            foreach (Resource res in bd.ResourceList) {
                if (res.Build) {
                    this.listBox1.Items.Add(new MyListItem("------@ RESOURCE:[" + res.Name + "][Y] ------", ""));
                    foreach (ResFile f in res.FileList) {
                        this.listBox1.Items.Add(new MyListItem(f.DstDir + f.Name, f.Path));
                    }
                } else
                    this.listBox1.Items.Add(new MyListItem("------# RESOURCE:[" + res.Name + "][N] ------", ""));
            }
        }

        public class MyListItem{
            public MyListItem(String txt, String path) {
                this._Text = txt;
                this._Path = path;
            }
            private String _Text = "";
            public String Text {
                set { _Text = value; }
                get { return _Text; }
            }
            private String _Path = "";
            public String Path {
                set { _Path = value; }
                get { return _Path; }
            }
        }
        private void ShowLog(String msg,int type) {
            this.rtxtView.Refresh();
            if (type == 0) {
                this.rtxtView.Text += "\n" + msg;
            } else {
                this.rtxtView.Text += "\n----" + msg;
            }
        }
        private String readAttr(XmlNode n,String attr,String def){
            if (n.Attributes[attr] != null) {
                return n.Attributes[attr].Value;
            } else {
                return def;
            }
        }
        private String parseDir(String path){
            if (String.IsNullOrEmpty(path)) {
                path = "";
            } else if (path.Substring(path.Length - 1, 1) != "/") {
                path += "/";
            }
            return path;
        }

        private void tsbtnPackage_Click(object sender, EventArgs e) {
            this.rtxtSelected.Text = "";
            if (!loaded) {
                doc.Load(_JskitPath);
                loaded = true;
            }
            this.rtxtSelected.Text = "执行打包....";
            this.rtxtView.Text = "";
            BuildDoc bd = parse2BuildDoc(doc);
            if (!Directory.Exists(bd.OutPath)) {
                Directory.CreateDirectory(bd.OutPath);
            }
            String content = "";
            Double size = 1;
            foreach (Package p in bd.PackageList) {
                StringBuilder sb = new StringBuilder("/*V."+bd.Version+",Packaged By [JEdwon Tunes],AnyRock@mending.cn,Copyright2006-2012,All right reserved*/");
                ShowLog("打包[  " + p.OutPath+"  ]",0);
                if (!p.Build) {
                    ShowLog("设置为跳过",1);
                    continue;
                }
                foreach (JsFile j in p.FileList) {
                    ShowLog("检查：" + j.Name + "", 0);
                    if (!File.Exists(j.Path)) {
                        ShowLog("错误：无法从位置[" + j.Path + "]找到文件", 1);
                        continue;
                    } else {
                        content = JsParser.ParseJsFile2Zipped(j.Name, j.Path);
                        size = Convert.ToDouble(content.Length/1024);
                        if (size < 1) size = 1;
                        ShowLog("加载：" + j.Name + ", "+Math.Ceiling(size)+"K",1);
                        sb.Append(content); 
                    }
                }
                try {
                    File.WriteAllText(p.OutPath, sb.ToString());
                    ShowLog("保存成功!",0); 
                    ShowLog("位置:[" + p.OutPath + "]",0);
                } catch (Exception ex) {
                    ShowLog("错误：保存打包文件失败：" + ex.Message,0);
                } finally {
                }
                ShowLog("----------------------------------",0);
            }//for package finished
            foreach (Resource res in bd.ResourceList) {
                ShowLog("拷贝资源：["+res.Name+"]",0);
                if (!res.Build) {
                    ShowLog("设置为跳过",1);
                    continue;
                }
                foreach (ResFile f in res.FileList) {
                    ShowLog("检查：[" + f.Name + "]",0);
                    try {
                        if (!Directory.Exists(f.DstDir)) { 
                            Directory.CreateDirectory(f.DstDir);
                        }
                        if (!File.Exists(f.Path)) {
                            ShowLog("错误：无法从位置[" + f.Path + "]找到源文件",1);
                        } else if (!Directory.Exists(f.DstDir)) {
                            ShowLog("错误：目标文件夹[" + f.DstDir + "]不存在",1);
                        } else {
                            File.Copy(f.Path, f.DstDir+f.Name, true);
                        }
                    } catch (Exception ex) {
                        ShowLog("错误：拷贝文件时出现异常["+ex.Message+"]",1);
                    }
                    ShowLog("复制完成！",1);
                }
                ShowLog("----------------------------------",0);
            }
            this.rtxtSelected.Text = "执行结束";
        }

        private void tsbtnClose_Click(object sender, EventArgs e) {
            this.Close();
        }

        private void tsbtnOpen_Click(object sender, EventArgs e) {
            String lastPath = loadLastFile();
            if (!String.IsNullOrEmpty(lastPath)) {
                this.openFileDialog1.FileName = lastPath;
            }
            DialogResult dr = this.openFileDialog1.ShowDialog();
            if (dr == DialogResult.OK) {
                _JskitPath = this.openFileDialog1.FileName;
                //Ctrls.BindDirFile2Tree(_JskitPath, this.treeView1.Nodes);
                ParseBuildConfig();

                this.tsbtnPackage.Enabled = true;
                if (!_JskitPath.Equals(lastPath)) {
                    saveLastFile(_JskitPath);
                }
            }
        }

    }
}
